#include "pch.h"
#include "PuyaDevice.h"
#include "tchar.h"

CPuyaDevice::CPuyaDevice()
	: m_bRun(true)
	, m_interface_number(3)
	, m_vendor_id(VID)
	, m_product_id(PID)
	, m_dev_handle(NULL)
	, m_pDevicePrintf(NULL)
	, m_pCnComm(NULL)
	, m_ucDtrRts(0)
{
	//libusb_init(NULL);
}

CPuyaDevice::~CPuyaDevice()
{
	if (NULL != m_pCnComm) {
		delete m_pCnComm;
	}	
	//usb_close();
	//libusb_exit(NULL);
}

bool CPuyaDevice::ReadDataEx(BYTE* pBuffer, DWORD dwLength, DWORD dwWaitTime)
{
	DWORD dwRead = 0;

	while (m_bRun && dwWaitTime--)
	{
		dwRead = m_pCnComm->Read(pBuffer, dwLength);

		if (dwRead) {
			pBuffer += dwRead;
			dwLength -= dwRead;
			if (0 == dwLength) {
				return true;
			}
		}
	}
	return false;
}

#if 0
int CPuyaDevice::usb_get_device_list(uint16_t vendor_id, uint16_t product_id)
{
	libusb_device** dev_list;
	ssize_t dev_list_cnt = 0;
	ssize_t dev_find_cnt = 0;
	libusb_device_descriptor dev_desc;

	m_vendor_id = vendor_id;
	m_product_id = product_id;

	dev_list_cnt = libusb_get_device_list(NULL, &dev_list);
	if (dev_list_cnt < 0) {
		return (int)dev_find_cnt;
	}

	for (ssize_t i = 0; i < dev_list_cnt; i++)
	{
		libusb_get_device_descriptor(dev_list[i], &dev_desc);

		if (m_vendor_id == dev_desc.idVendor && m_product_id == dev_desc.idProduct)
		{
			dev_find_cnt++;			
		}
	}

	libusb_free_device_list(dev_list, 1);

	return (int)dev_find_cnt;
}

int CPuyaDevice::usb_open(int interface_number, int dev_list_index)
{
	int nErrCode = ERROR_USB_OPEN;
	libusb_device** dev_list;
	ssize_t dev_find_cnt = 0;
	libusb_device_descriptor dev_desc;

	m_interface_number = interface_number;

	for (ssize_t i = 0; i < libusb_get_device_list(NULL, &dev_list); i++)
	{
		libusb_get_device_descriptor(dev_list[i], &dev_desc);

		if (m_vendor_id == dev_desc.idVendor && m_product_id == dev_desc.idProduct)
		{
			if (dev_list_index == dev_find_cnt)
			{
				nErrCode = libusb_open(dev_list[i], &m_dev_handle);
				break;
			}

			dev_find_cnt++;
		}
	}

	if (NULL == m_dev_handle) {
		return ERROR_USB_OPEN;
	}

	libusb_free_device_list(dev_list, 1);

	for (int i = m_interface_number; i >= 0; i--){
		nErrCode = libusb_claim_interface(m_dev_handle, i);
		if (0 == nErrCode) {
			break;
		}
	}

	return nErrCode;
}

void CPuyaDevice::usb_close(void)
{
	if (NULL != m_dev_handle) {
		libusb_release_interface(m_dev_handle, m_interface_number);
		libusb_close(m_dev_handle);
		m_dev_handle = NULL;
	}
}

int CPuyaDevice::usb_bulk_transfer(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout)
{
	int actual_length = 0;
	libusb_bulk_transfer(m_dev_handle, endpoint, data, length, &actual_length, timeout);
	return actual_length;
}

int CPuyaDevice::usb_interrupt_transfer(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout)
{
	int actual_length = 0;
	do {
		libusb_interrupt_transfer(m_dev_handle, endpoint, data, length, &actual_length, 1000);
		timeout -= 1000;
	} while (m_bRun && (!actual_length) && timeout);
	return actual_length;
}
#endif

uint32_t CPuyaDevice::Init(uint32_t nPort, uint32_t nSpeed)
{
	DevicePrintf(_T("CPuyaDevice::Init"));
	return 0;
}

uint32_t CPuyaDevice::Uninit(void)
{
	DevicePrintf(_T("CPuyaDevice::Uninit"));
	return 0;
}

uint32_t CPuyaDevice::WriteMemory(uint32_t addr, uint8_t* data, uint32_t size)
{
	DevicePrintf(_T("CPuyaDevice::WriteMemory"));
	return 0;
}

uint8_t  CPuyaDevice::ReadMemory(uint32_t addr, uint8_t* data, uint32_t size)
{
	DevicePrintf(_T("CPuyaDevice::ReadMemory"));
	return 0;
}

uint32_t CPuyaDevice::ErasePage(uint8_t* data, uint32_t size)
{
	DevicePrintf(_T("CPuyaDevice::ErasePage"));
	return 0;
}

uint32_t CPuyaDevice::EraseSector(uint8_t* data, uint32_t size)
{
	DevicePrintf(_T("CPuyaDevice::EraseSector"));
	return 0;
}

uint32_t CPuyaDevice::EraseChip(void)
{
	DevicePrintf(_T("CPuyaDevice::EraseChip"));
	return 0;
}

uint8_t CPuyaDevice::Go(uint32_t addr)
{
	DevicePrintf(_T("CPuyaDevice::Go"));
	return 0;
}

//uint32_t CPuyaDevice::WriteOptionBytes(uint32_t addr, uint8_t* data, uint32_t size)
//{
//	DevicePrintf(_T("CPuyaDevice::WriteOptionBytes"));
//	return 0;
//}

void CPuyaDevice::DevicePrintf(const TCHAR* __restrict format, ...)
{
	if (NULL != m_pDevicePrintf){

		TCHAR szContent[1024] = { 0 };

		va_list arglist;
		va_start(arglist, format);
		_vsntprintf_s(szContent, 1024, format, arglist);
		va_end(arglist);

		m_pDevicePrintf(szContent);
	}
}
